package com.ideal.tools.ssh.operation;

import com.ideal.tools.ssh.common.CommonTools;
import com.ideal.tools.ssh.context.ClusterContext;
import com.ideal.tools.ssh.entity.LinuxCommand;
import com.ideal.tools.ssh.entity.SSHAuthor;
import com.ideal.tools.ssh.result.LinuxResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by CC on 2016/3/1.
 */
public abstract class LinuxOperation {

    public enum OperationType{
        EXE_CMD, //普通命令行操作
        SCP_UPLOAD,   //使用scp上传文件
        SCP_DOWNLOAD, //使用scp下载文件
        FTP_UPLOAD,    //使用ftp
        FTP_DOWNLOAD   //使用ftp
    }
    private static Logger logger = LoggerFactory.getLogger(LinuxOperation.class);
    private LinuxCommand linuxCommand;
    private LinuxResult operationResult;
    private SSHAuthor sshAuthor;    //这个是执行的远程本机  根据machine来初始
    private SSHAuthor fromSSHAuthor;//这个是提供下载的地址  从具体实现类拿

    public abstract void execLinuxCMD(ClusterContext context);

    /**
     * 执行操作 会写出来时因为 这个都是公共代码
     * 这里加入 时间不帅 后面用别的来实现
     * @param context
     */
    protected void execOperation(ClusterContext context){
        long startTime = System.currentTimeMillis();
        //获取连接
        operationResult = context.getCurMachine().connectMachine(this);

        //初始化 连接信息 这个放入 是为了 后面方便使用
        initSSHAuth(context.getCurMachine().getSshAuthor());

        //放入执行命令
        operationResult.setCmd(linuxCommand.getCommand());

        //判断是否连接成功
        if(operationResult.getExitCode() == LinuxResult.DEFAULT_SUCCESS_CODE){
            //TODO: 2016/4/22 很慢
            operationResult = (LinuxResult)operationResult.getSshExecutor().exec(linuxCommand);
        }
        //组织前台note
        setResultNote(operationResult);

        long endTime =System.currentTimeMillis();
        logger.warn("exe time:"+ CommonTools.getFormateTime(startTime)
                +"-"+CommonTools.getFormateTime(endTime)+" use time:"+(endTime-startTime)
                +" cmd:"+linuxCommand.getCommand());
        logger.warn("exit code:"+operationResult.getExitCode());
    }



    /**
     * 获取 运行结果的唯一途径
     * @return
     */
    public LinuxResult getExeResult(){
        return operationResult;
    }

    /**
     * 定义每个 操作的类型
     * 默认为linux 命令行 操作
     * @return
     */
    public  OperationType getOperatType(){
        return OperationType.EXE_CMD;
    }

    /**
     * 获取cmd
     * @return
     */
    public LinuxCommand getLinuxCommand() {
        return linuxCommand;
    }

    /**
     * 初始化cmd
     * @param linuxCommand
     */
    public void setLinuxCommand(LinuxCommand linuxCommand) {
        this.linuxCommand = linuxCommand;
    }

    /**
     * 这个需要根据每个 具体的实现类 加入不同的 操作备注
     * @param linuxResult
     */
    public abstract void setResultNote(LinuxResult linuxResult);

    public LinuxOperation initSSHAuth(SSHAuthor sshAuthor){
        this.sshAuthor=sshAuthor;
        return this;
    }

    public LinuxOperation initFromSSHAuth(SSHAuthor fromSSHAuthor){
        this.fromSSHAuthor=fromSSHAuthor;
        return this;
    }

    public SSHAuthor getSshAuthor() {
        return sshAuthor;
    }

    public SSHAuthor getFromSSHAuthor() {
        return fromSSHAuthor;
    }

    /*************************下面这些都属于一些不定要加在 这个抽象类里面的方法 加进来只是为了方便使用*****************************/
    public String getHost(){
//        if(sshAuthor)
        return sshAuthor.getHost();
    }

    public String getResultInfo(){
        String info="";
        String exception = getExeResult().getException();
        String stdOut = getExeResult().getStdOut();
        String errOut = getExeResult().getErrOut();
        if(!StringUtils.isBlank(stdOut)){
            info = info + "Info["+stdOut.trim()+"]\n";
        }
        if(!StringUtils.isBlank(exception)){
            info = info + "Exception["+exception.trim()+"]\n";
        }
        if(!StringUtils.isBlank(errOut)){
            info = info + "Error["+errOut.trim()+"]\n";
        }

        return info;
    }

    public SSHAuthor getOneSSHAuth(String host,String user,String passwd,String pubKey){
        SSHAuthor tmpSShAuth=new SSHAuthor();
        tmpSShAuth.setHost(host);
        tmpSShAuth.setUsername(user);
        tmpSShAuth.setPasswd(passwd);
        tmpSShAuth.setPubToken(pubKey);
        return tmpSShAuth;
    }


    /**
     * 这个方法用来确认 这个操作的标识
     * @return
     */
    public String getLinuxOperationID(){
        return this.getClass().getSimpleName();
    }

}

